/**
 * 事件管理器类 - 用于处理画布的缩放和拖拽功能
 * 管理画布的交互事件，包括鼠标滚轮缩放和鼠标拖拽平移
 */
export class EventManager {
    /**
     * @param {HTMLElement} container - 容器元素，用于添加事件监听
     * @param {PIXI.Application} app - PIXI应用实例，用于控制舞台的缩放和位置
     */
    /**
     * @param {HTMLElement} container - 容器元素，用于添加事件监听
     * @param {PIXI.Application} app - PIXI应用实例，用于控制舞台的缩放和位置
     * @param {Object} options - 配置选项
     * @param {number} [options.scaleBy=1.1] - 每次缩放的比例
     * @param {number} [options.minScale=0.1] - 最小缩放比例
     * @param {number} [options.maxScale=10] - 最大缩放比例
     * @param {boolean} [options.isEnabled=true] - 是否启用事件处理
     */
    constructor(container, app, options = {}) {
        this.container = container;
        this.app = app;
        this.isDragging = false; // 是否正在拖拽中
        this.lastPosition = { x: 0, y: 0 }; // 记录上一次鼠标位置
        this.scaleBy = options.scaleBy ?? 1.1; // 每次缩放的比例
        this.minScale = options.minScale ?? 0.1; // 最小缩放比例
        this.maxScale = options.maxScale ?? 10; // 最大缩放比例
        this.dragStartTime = 0; // 记录拖拽开始时间
        this.isEnabled = options.isEnabled ?? true; // 是否启用事件处理
        this.eventListeners = {}; // 初始化事件监听器对象
        this.lastPinchDistance = 0; // 记录上一次双指捏合的距离
        this.isPinching = false; // 是否正在进行双指缩放
        this.init();
    }

    /**
     * 初始化事件监听
     * 绑定鼠标滚轮、拖拽相关的事件处理函数
     */
    init() {
        this.container.addEventListener('wheel', this.handleWheel.bind(this), { passive: false });
        this.container.addEventListener('mousedown', this.handleDragStart.bind(this));
        this.container.addEventListener('mousemove', this.handleDragMove.bind(this));
        this.container.addEventListener('mouseup', this.handleDragEnd.bind(this));
        this.container.addEventListener('mouseleave', this.handleDragEnd.bind(this));
        
        // 添加触摸事件支持
        this.container.addEventListener('touchstart', this.handleTouchStart.bind(this));
        this.container.addEventListener('touchmove', this.handleTouchMove.bind(this));
        this.container.addEventListener('touchend', this.handleTouchEnd.bind(this));
        this.container.addEventListener('touchcancel', this.handleTouchEnd.bind(this));
    }

    /**
     * 处理鼠标滚轮事件
     * 实现画布的缩放功能
     * @param {WheelEvent} e - 滚轮事件对象
     */
    // 处理鼠标滚轮事件
    handleWheel(e) {
        // 如果组件不可用，则返回
        if (!this.isEnabled) return;
        // 阻止默认事件
        e.preventDefault();

        // 获取鼠标在canvas中的位置
        const rect = this.app.view.getBoundingClientRect();
        const mouseX = e.clientX - rect.left;
        const mouseY = e.clientY - rect.top;

        // 获取鼠标相对于stage的本地坐标
        const localPos = this.app.stage.toLocal({ x: mouseX, y: mouseY });

        // 获取当前缩放比例
        const currentScale = this.app.stage.scale.x;
        // 根据滚轮方向计算新的缩放比例
        const newScale = e.deltaY < 0 ? currentScale * this.scaleBy : currentScale / this.scaleBy;

        // 限制缩放范围在最小和最大值之间
        if (newScale >= this.minScale && newScale <= this.maxScale) {
            // 计算缩放前后的坐标差
            const beforeTransform = this.app.stage.toGlobal(localPos);
            // 设置新的缩放比例
            this.app.stage.scale.set(newScale);
            const afterTransform = this.app.stage.toGlobal(localPos);
            // 调整stage位置，使鼠标指向的点保持在原位置
            this.app.stage.position.x += (beforeTransform.x - afterTransform.x);
            this.app.stage.position.y += (beforeTransform.y - afterTransform.y);
        }
        this.emit('zoom', { scale: newScale });
    }

    /**
     * 处理拖拽开始事件
     * @param {MouseEvent} e - 鼠标事件对象
     */
    handleDragStart(e) {
        if (e.button !== 0 && e.button !== 1) return; // 同时支持左键和中键点击
        if (!this.isEnabled) return;
        this.isDragging = true;
        this.lastPosition = { x: e.clientX, y: e.clientY };
        this.dragStartTime = Date.now();
    }

    handleTouchStart(e) {
        if (!this.isEnabled) return;
        e.preventDefault(); // 阻止默认行为

        if (e.touches.length === 2) {
            // 双指触摸，进入缩放模式
            this.isPinching = true;
            this.isDragging = false;
            // 计算初始双指距离
            const touch1 = e.touches[0];
            const touch2 = e.touches[1];
            this.lastPinchDistance = Math.hypot(
                touch2.clientX - touch1.clientX,
                touch2.clientY - touch1.clientY
            );
        } else {
            // 单指触摸，进入拖拽模式
            this.isPinching = false;
            this.isDragging = true;
            const touch = e.touches[0];
            this.lastPosition = { x: touch.clientX, y: touch.clientY };
            this.dragStartTime = Date.now();
        }
    }

    handleTouchMove(e) {
        if (!this.isEnabled) return;
        e.preventDefault(); // 阻止默认行为

        if (e.touches.length === 2 && this.isPinching) {
            // 处理双指缩放
            const touch1 = e.touches[0];
            const touch2 = e.touches[1];
            const currentDistance = Math.hypot(
                touch2.clientX - touch1.clientX,
                touch2.clientY - touch1.clientY
            );

            // 计算缩放中心点
            const centerX = (touch1.clientX + touch2.clientX) / 2;
            const centerY = (touch1.clientY + touch2.clientY) / 2;
            const rect = this.app.view.getBoundingClientRect();
            const localPos = this.app.stage.toLocal({
                x: centerX - rect.left,
                y: centerY - rect.top
            });

            // 计算缩放比例
            const scale = currentDistance / this.lastPinchDistance;
            const currentScale = this.app.stage.scale.x;
            const newScale = currentScale * scale;

            // 限制缩放范围
            if (newScale >= this.minScale && newScale <= this.maxScale) {
                const beforeTransform = this.app.stage.toGlobal(localPos);
                this.app.stage.scale.set(newScale);
                const afterTransform = this.app.stage.toGlobal(localPos);

                // 调整位置保持缩放中心点不变
                this.app.stage.position.x += (beforeTransform.x - afterTransform.x);
                this.app.stage.position.y += (beforeTransform.y - afterTransform.y);
            }

            this.lastPinchDistance = currentDistance;
            this.emit('zoom', { scale: newScale });
        } else if (this.isDragging) {
            // 处理单指拖拽
            const touch = e.touches[0];
            const dx = touch.clientX - this.lastPosition.x;
            const dy = touch.clientY - this.lastPosition.y;
            
            this.app.stage.position.set(
                this.app.stage.position.x + dx,
                this.app.stage.position.y + dy
            );

            this.lastPosition = { x: touch.clientX, y: touch.clientY };
            this.emit('drag', { x: dx, y: dy });
        }
    }

    handleTouchEnd(e) {
        if (!this.isEnabled) return;
        this.isDragging = false;
        this.isPinching = false;
        this.lastPinchDistance = 0;
        this.emit('dragEnd');
    }

    /**
     * 处理拖拽移动事件
     * 实现画布的平移功能
     * @param {MouseEvent} e - 鼠标事件对象
     */
    handleDragMove(e) {
        if (e.button !== 0 && e.button !== 1) return; // 同时支持左键和中键点击
        if (!this.isEnabled || !this.isDragging) return;
        const dx = e.clientX - this.lastPosition.x;
        const dy = e.clientY - this.lastPosition.y;
        this.app.stage.position.set(
            this.app.stage.position.x + dx,
            this.app.stage.position.y + dy
        );

        this.lastPosition = { x: e.clientX, y: e.clientY };
        this.emit('drag', { x: dx, y: dy });
    }

    /**
     * 处理拖拽结束事件
     */
    handleDragEnd(e) {
        if (!this.isEnabled) return;
        this.isDragging = false;
        this.emit('dragEnd');
    }

    /**
     * 添加事件监听器
     * @param {string} eventName - 事件名称
     * @param {Function} callback - 回调函数
     */
    on(eventName, callback) {
        if (!this.eventListeners[eventName]) {
            this.eventListeners[eventName] = [];
        }
        this.eventListeners[eventName].push(callback);
    }

    /**
     * 触发事件
     * @param {string} eventName - 事件名称
     * @param {*} data - 事件数据
     */
    emit(eventName, data) {
        const listeners = this.eventListeners[eventName];
        if (listeners) {
            listeners.forEach(callback => callback(data));
        }
    }

    /**
     * 销毁事件管理器
     * 移除所有事件监听
     */
    /**
     * 事件类型和处理函数映射
     */
    get eventHandlers() {
        return [
            ['wheel', this.handleWheel],
            ['mousedown', this.handleDragStart],
            ['mousemove', this.handleDragMove],
            ['mouseup', this.handleDragEnd],
            ['mouseleave', this.handleDragEnd]
        ];
    }
    /**
     * 销毁事件管理器
     */
    destroy() {
        this.container.removeEventListener('wheel', this.handleWheel);
        this.container.removeEventListener('mousedown', this.handleDragStart);
        this.container.removeEventListener('mousemove', this.handleDragMove);
        this.container.removeEventListener('mouseup', this.handleDragEnd);
        this.container.removeEventListener('mouseleave', this.handleDragEnd);
    }

    /**
     * 禁用事件监听
     */
    disable() {
        this.isEnabled = false;
    }

    /**
     * 启用事件监听
     */
    enable() {
        this.isEnabled = true;
    }
}